
export default class MyVue17 {
    // 构造函数
    constructor(config) {
        this.beforeCreate = config.beforeCreate ?? undefined
        this.created = config.created ?? undefined

        // 1.平铺配置对象 和 添加 响应式 环节-----------------------
        // beforeCreate: 平铺 属性 到 vue实例之前执行
        this.beforeCreate && this.beforeCreate()
        for (let key in config.data) {
            // a.向 当前 vue实例 添加同名属性
            //   并 将 属性值 设置给它
            this[key] = config.data[key] //  {dogName:'ruiky'}
            // b.将 vue实例 中 指定的key属性，改成 响应式属性
            this.defineReactive(this, key)
        }
        // created: 平铺 属性 到 vue实例之后执行
        this.created && this.created()

        // 2.编译视图+虚拟dom+真实dom渲染环节-----------------------
        // beforeMount:
        // mounted:

        // ......
    }

    // 将 指定的 属性 转成 响应式属性(getter/setter)
    // 情况1：对象中 本来就有这个属性，需要改造成 响应式属性
    // 情况2：对象中 本来没有这个属性，需要 为对象 添加 新的 响应式属性
    defineReactive(obj, key, val) {
        // 1.如果 只传入对象 和 属性名，则说明 对象中 已经有 该属性了
        if (arguments.length === 2) {
            // 2.将 属性值 设置给 形参 val，保存起来，后面当闭包使用
            val = obj[key]
        }
        // 2.为这个属性 设置观察者，并将所有属性改成 响应式属性
        MyVue17.observe(val)
        // 3.改造成 响应式属性
        Object.defineProperty(obj, key, {
            enumerable: true,
            // value:
            get() {
                return val
            },
            set(nV) {
                val = nV
                // 调用观察者 中的 dep 内部 注册的 订阅者函数
                // 订阅者函数 就会 跟新 所属的 组件的 视图标签
            }
        })
    }

    // 为传入数据【对象】添加观察者,并将属性改造成响应式属性
    static observe(val) {
        // 1.判断传入的 是否为对象
        if (typeof val !== 'object') {
            // 如果不是对象，则直接范围
            return
        }

        // 2.如果是对象，则为 对象添加 __ob__ 观察者属性
        if (typeof val.__ob__ !== 'undefined') {

        } else {
            // 添加 观察值对象
            val.__ob__ = new Observer(val)
        }
    }
}

// 观察者 类 - a.遍历当前所在的对象的 属性，将他们改造成 响应式属性
//            b.为自己本身 添加一个 dep（订阅者集合）
class Observer {
    // 构造函数
    constructor(obj) {
        this.walk(obj)
    }

    // 遍历 对象中所有的属性，将他们 改造成 响应式属性
    walk(obj) {
        for (let k in obj) {
            // 判断 当前属性 是否为对象，如果是，则添加 观察者对象()
            if (typeof obj[k] === 'object') {
                MyVue17.observe(obj[k])
            }
            // 改造成 响应式属性
            this.defProperty(obj, k)
        }
    }

    defProperty(obj, key, value) {
        value = obj[key]
        Object.defineProperty(obj, key, {
            enumerable: true,
            // value,
            // writable: true,
            configurable: true,
            get() {
                return value
            },
            set(n) {
                value = n
            }
        })
    }
}